<?php
/**
 * @TODO 未完成,待修改 
 */

/**
 * 默认Session管理
 * 
 * ============================================================================
 * 版权所有: (c) 2009-2011，<UEShop Inc>，并保留所有权利。
 * 网站地址: http://www.ueshop.cn
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 *
 * @author      cmpan
 * @copyright   Copyright (c) 2009-2010 UEShop Inc. (http://www.ueshop.cn)
 * @license     http://www.ueshop.cn/1_0.txt
 */
final class UE_Session_DB implements UE_Session_Interface {
	protected $_db = null;

	public function __construct() {
		$this->_db = UE_DB::factory();
	}

	public function start() {
		if (ini_get('session.auto_start')) {
			session_destroy();
		    unset($_SESSION);
		}
		
		session_set_save_handler(
			array(&$this, 'open'),
			array(&$this, 'close'),
			array(&$this, 'read'),
			array(&$this, 'write'),
			array(&$this, 'destroy'),
			array(&$this, 'gc')
		);
		session_start();
	}

	/**
	 * 运行到 session_start()后程序就进入这个函数
	 *
	 * @param string $savePath
	 * @param string $sessionName
	 * @return bool
	 */
	public function open($savePath, $sessionName){
		return true;
	}

	/**
	 * 程序运行完UE_Session_DB::open()后接着进入这里
	 *
	 * @param string $id
	 * @return bool
	 */
	public function read($sid){
		$sess = $this->_db->getOne("SELECT session_data, session_user_ip FROM ue_session WHERE session_id = '$sid'");
		if(!$sess) {
			return '';
		}

		// 验证IP
		if(UE_IP::realIp() != $sess['session_user_ip']) {
			$this->destroy($sid);
			$this->start();
			return '';
		}

		$sessData = $sess['session_data'];

		if (isset($sessData[255])) {
			$field = $this->_db->getFirstField("SELECT session_data FROM ue_session_data WHERE session_id = '$sid'");
			if ($field) {
				$sessData = $field;
			}
		}
		
		return $sessData;
	}

	/**
	 * 当所有析构函数运行完以后程序进入这里
	 *
	 * @param string $id
	 * @param string $sessData
	 * @return bool
	 */
	public function write($sid, $sessData){
		$time = time();
		if (strlen($sessData) > 255) {
			$this->_db->query("REPLACE INTO `ue_session_data` SET session_id = '$sid', lastactivity = '$time', sessdata = '$sessData';");
			$sessData = substr($sessData, 255);
		}
		
		extract($_SESSION, EXTR_OVERWRITE);
		
		$sql = "REPLACE INTO `yl_sessions`
	 		    SET `sid`          = '$sid',
	 		        `app`          = '" . $_GET['app'] . "',
	 		        `ctl`          = '" . $_GET['ctl'] . "',
	 		        `act`          = '" . $_GET['act'] . "',
	 		        `id`           = '" . $_GET['id'] . "',
	 		        `lastactivity` = '$time',
	 		        `sessData`     = '$sessData',
				    `ip`           = '{$ip}',
	 		        `uid`          = '{$uid}',
	 		        `userName`     = '{$userName}',
	 		        `password`     = '{$password}',
	 		        `groupid`      = '{$groupId}',
	 		        `admingroupid` = '{$adminGroupId}',
	 		        `invisible`    = '{$invisible}';";
		$this->_db->query($sql);

		return true;
	}

	/**
	 * 运行UE_Session_DB::write()以后接着就进入这里，然后退出php进程
	 *
	 * @return bool
	 */
	public function close(){
		$sessionStatFile = DATA_DIR . '/temp/sessionStatFile.php';
		clearstatcache();
		if(!is_file($sessionStatFile) || time() - @filemtime($sessionStatFile) > ini_get('session.gc_maxlifetime')) {
			file_put_contents($sessionStatFile, '', LOCK_EX);
			$this->gc(ini_get('session.gc_maxlifetime'));
		}
		return true;
	}

	public function destroy($sid){
		setcookie(session_name(), '', time() - 3600);
		$_SESSION = array();
		$this->_db->query("DELETE FROM `yl_sessions` WHERE `sid` = '$sid'");
		$this->_db->query("DELETE FROM `yl_sessions_data` WHERE `sid` = '$sid'");
		return true;
	}

	public function gc($maxLifeTime){
		$expire = time() - $maxLifeTime;
		$this->_db->query("DELETE FROM yl_sessions WHERE lastactivity < '$expire'");
		$this->_db->query("DELETE FROM yl_sessions_data WHERE lastactivity < '$expire'");
		return true;
	}
}